#导入蓝图模块
from datetime import datetime
from re import I, U
from flask import Blueprint,request
#导入基础模块
from flask import request,jsonify,send_from_directory
from flask.scaffold import F
import requests
from pymysql.connections import DEBUG
 
from flask_cors import CORS
#导入数据库操作类
from db import Db,make_password
#导入加密类
from myJWT import MyJwt
from flask import redirect
#实例化蓝图
user = Blueprint("/user",__name__)
CORS(user)
import os
from myfile import MyFile
import time
import hmac
import base64
from hashlib import sha256
import urllib
import json

#导入类视图
from flask.views  import MethodView
import redis
#父级登录类

class UserAPI(MethodView):
    #公共方法
    def get_code(self,phone):
        self.db = Db()
        self.r = redis.Redis()
        code = self.r.get(phone)
        return code
class UserLogin(UserAPI):
    def get(self):
        self.db = Db()
        username = request.args.get('username')
        password = request.args.get('password')
        sql = " select * from `users` where username = '%s' and password = '%s' " % (username,make_password(password))
        res = self.db.get_one(sql)
        if res:
            myjwt = MyJwt()
            token = myjwt.encode_jwt({'id':res['id'],'username':res['username']})
            return {'code':200,'msg':'登录成功','username':res['username'],'token':token,'id':res['id']}
        else:
            return {'code':400,'msg':'你的用户名或密码错误'}
        
#手机号登录
class PhoneAPI(UserAPI):
    def get(self):
        #获取验证码
        phone = request.args.get('phone')
        code1 = request.args.get('code')
        r_code = self.get_code(phone)
        try:
           codee =r_code.decode('utf-8')
        except Exception as e:
            return {'code':10011,'msg':'没有发送验证码'}

        if codee is None:
            return {'code':403,'msg':'你的验证码已经过期'}
        if code1 == codee:
            res = self.db.get_one(" select id,username from `users` where phone = '%s' " % phone)
            if res:
                return {'code':200,'msg':'登录成功',"id":res['id'],"username":res['username']}
            else:
                self.db.insert(" insert into `users` (`username`,`password`,`phone`) values ('%s','%s','%s') " % (phone,'',phone))
                res = self.db.get_one(" select id,username from `users` where phone = '%s' " % phone)
                return {'code':200,'msg':"登录成功","id":res['id'],"username":res['username']}
        else:
            return {'code':403,'msg':"您的验证码有误"} 
#邮箱登录
class EmailAPI(UserAPI):
    def get(self):
        #获取验证码
        email = request.args.get('email')
        password = request.args.get('password')
        self.db = Db()
        res = self.db.get_one("select * from `users` where email='%s' "%email)
        if res:
            if res['password'] == make_password(password):
                myjwt = MyJwt()
                token = myjwt.encode_jwt({'id':res['id'],'username':res['email']})
                return {'code':200,'msg':'登录成功','username':res['email'],'token':token}
            else:
                return {'code':400,'msg':'密码错误'}
        else:
            return {'code':10010,'msg':'邮箱不存在'}
#路由 
user.add_url_rule('/phonelogin/',view_func=PhoneAPI.as_view('/phonelogin/'))
user.add_url_rule('/emailLogin/',view_func=EmailAPI.as_view('/emaillogin/'))
user.add_url_rule('/userLogin/',view_func=UserLogin.as_view('/userLogin/'))







#图片修改
@user.route('/uploadfile/',methods=['PUT'])
def uploadfile():
    try:
        id = request.form.get('id')
        oldfile = request.form.get('oldfile')
        newfile= request.form.get('newfile')
        print(id,oldfile,newfile)
        myfile = MyFile()
        myfile.put(id,oldfile,newfile)
        return {'code':200,'meg':'修改成功'}
    except Exception as e:
        return {'code':400}


#文件下载
@user.route('/download/',methods=['GET'])
def download():
    id = request.args.get('id')
    filename = request.args.get('filename')
    return send_from_directory('./static/upload/'+str(id),filename,as_attachment=True)


@user.route('/delfile/',methods=['DELETE'])
def delfile():
    try:
        id = request.args.get('id')
        filename = request.args.get('filename')
        myfile = MyFile()
        myfile.remove(id,filename)
        return {'code':200,'meg':'删除成功'}
    except Exception as e:
        return {'code':400}

@user.route('/filelist_sorted/',methods=['GET'])
def filelist_sorted():
    id = request.args.get('id')
    reverse = request.args.get('reverse','False')
    back = request.args.get('back','False')
    #后缀的正序或者倒叙
    back_reverse = request.args.get('back_reverse','False')
    print(reverse,back,back_reverse)
    mf = MyFile()
    mylist =mf.list_dir(id,eval(reverse),eval(back),eval(back_reverse))
    return jsonify(mylist)

#文件列表接口
@user.route('/filelist/',methods=['GET'])
def filelist():
    id = request.args.get('id')
    print(id)
    reverse = request.args.get('reverse','False')
    back = request.args.get('back','False')
    #后缀的正序或者倒叙
    back_reverse = request.args.get('back_reverse','False')
    mf = MyFile()
    mylist =mf.list_dir(id,eval(reverse),eval(back),eval(back_reverse))
    return jsonify(mylist)

@user.route('/ding_url/')
#构造钉钉登录url
def ding_url():
    appid = 'dingoat3wizxmxykcjeqht'
    redirect_uri = 'http://localhost:5000/dingding_back/'
    return {'url':'https://oapi.dingtalk.com/connect/qrconnect?appid='+appid+'&response_type=code&scope=snsapi_login&state=STATE&redirect_uri='+redirect_uri}


@user.route('/dingding_back/')
#构造钉钉回调方法
def dingding_back():
    #获取code
    code = request.args.get("code")
    t = time.time()
    #时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret ='HbRbHVwTFTNnvvqxi4dr-7fli9sAuKen1hiyp8vI1qONXZTnfk0MXM_nv3vTxdil'
    #构造签名
    signature = base64.b64encode(hmac.new(appSecret.encode('utf-8'),timestamp.encode('utf-8'), digestmod=sha256).digest())
    #请求接口，换取钉钉用户名
    payload = {'tmp_auth_code':code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature='+urllib.parse.quote(signature.decode("utf-8"))+"&timestamp="+timestamp+"&accessKey=dingoat3wizxmxykcjeqht",data=json.dumps(payload),headers=headers)
    res_dict = json.loads(res.text)
    return jsonify(res.text)



from myupyun import MyUpyun
#文件上传接口
@user.route('/upload/',methods=['POST'])
def upload():
   f = request.files['file']
   id = request.form.get('id',1)
   courseid = request.form.get('cid',3)
   #上传类型  0图片 1视频 2音频
   upload_type = request.form.get('type',0)
   upload_type = int(upload_type)
   if upload_type == 0:
       #写文件
    #    f.save(os.path.join('./static/upload/'+str(id),f.filename))
       db = Db()
       db.update("update `users` set `img`='%s' where `id`=%s"%(f.filename,id))
       return {'code':200,'msg':'上传成功','filename':f.filename}
   else:
       db = Db()
       course = db.get_one("select * from `course` where id=%s"%courseid)
       if course:
           #重命名文件
           myfile = MyFile()
           newname = myfile.rename(f.filename)
           #做计数器限制
           r = redis.Redis()
           count_video = r.get('video')
           #转码
           try:
                count_video = str(count_video,'uft-8')
                count_video = int(count_video)
           except Exception as e:
               pass
           if count_video:
               if count_video >=3:
                   return {'code':403,'msg':'你今天上传视频个数达到了限制'}
               else:
                   #累加
                   r.incr('video')
           else:
               #24小时以内没有上传过视频
               #创建计数器  key 周期，value
               r.setex('video',30,1)
           if course['video']=="" or course['video'] is None:
               db.update("update `course` set `video`='%s' where id =%s"%('["'+newname+'"]',courseid))
           else:
               #该课程上传过
               videos = course['video']
               #转换实体
               videos= eval(videos)
               videos.append(newname)
               videos = str(videos)
               db.update("update `course` set `video`='%s' where id = %s"%(videos.replace("'","\""),courseid))
           f.save(os.path.join('./static/upload/'+str(id),newname))
           return {'code':200,'msg':"视频上传成功",'filename':newname}
       else:
           return {'code':403,'msg':'你所上传的课程不存在','filename':''}

@user.route('/addimage/',methods=['POST'])
def addimage():
    id = request.form.get('id')
    img = request.form.get('img')
    db=Db()
    try:
        db.update("update `users` set img='%s' where id='%s'"%(img,id))
    except Exception as e:
        return {'code':10010,'meg':'修改失败'}
    else:
        return {'code':200,'meg':'修改成功'}



#修改密码
@user.route('/put_password/',methods=['PUT'])
def put_password():
    username = request.form.get('username')
    id = request.form.get('id')
    password = request.form.get('password')
    password1 = request.form.get('newpassword')
    print(username,id,password1,password)
    db = Db()
    user = db.get_one("select * from `users` where `username`='%s'"%username)
    print(user['password'])
    print(make_password(password))
    if user and make_password(password) == user['password']:
        res = db.update("update `users` set password='%s' where id ='%s'"%(make_password(password1),id) )
        if res:
            return {'code':200,'meg':'修改成功'}
        else:
            return {'code':400,'meg':'修改失败'}
    return {'code':10010,'meg':'原密码错误'}
        
        


#flask中间件使用
@user.before_request
def  before_request():
    if request.path in ['userinfo/']:
        id = request.args.get('id',0)
        token = request.args.get('token')
        myjwt = MyJwt()
        try:
             tokens = myjwt.decode_jwt(token)
        except Exception as e:
                return {'code':10010,'meg':'秘钥不合法'}
        if str(tokens['id']) != str(id):
            return {'code':403,'meg':'你无权访问用户信息'}
        print('经过了中间件')
        print(request.path)

#获取用户信息
@user.route('/userinfo/',methods=['GET'])
async def userinfo():
    id = request.args.get('id',0)
    db = Db()
    res = db.get_one("select * from  `users` where id='%s'"%id)
    res['code'] = 200
    return jsonify(res)
   
    



#注册
@user.route("/register/",methods = ['POST'])
def register():
    #接收参数
    username = request.form.get('username')
    password = request.form.get('password')
    #sql语句
    sql = "insert into `users` (`username`,`password`) values ('%s','%s')"%(username,make_password(password))
    db = Db()
    try:
            #添加数据
         db.insert(sql)
    except Exception as e:
            return {'code':400,'meg':'该用户已存在'}
    else:
        user = db.get_one("select * from `users` where `username`='%s'"%username)
        # myfile = MyFile()
        #创建该用户文件夹存放图片
        # myfile.mkdir(user['id'])
        #创建又拍云存放路径
        # myUpyun = MyUpyun()
        # myUpyun.mkdir(user['id'])
        return {'code':200,'meg':'注册成功'}


import redis
from text_code import Code

@user.route('/send_code/',methods = ['POST','GET'])
def send_code():
    # phone = request.form.get('phone')
    phone = request.args.get('phone')
    conn = redis.Redis()
    rcode = conn.get(phone)
    if rcode:
        return {'code':400,'meg':'已经发送过短信'}
    code = Code()
    res = code.send_code(phone)
    return {'code':200,'meg':'发送成功','code1':res}
from db import Db
@user.route('/check_code/',methods=['POST','GET'])
def check_code():
    # phone = request.form.get('phone')
    # code = request.form.get('code')
    phone = request.args.get('phone')
    code = request.args.get('code')
    conn = redis.Redis()
    rcode = str(conn.get(phone),encoding='utf-8')
    if rcode == code:
        db = Db()
        res = db.get_one(" select id,username from `users` where phone='%s'"%phone)
        if res:
            return {'code':200,'meg':'验证成功','username':res['username'],'id':res['id']}
        else:
            db.insert("insert into `users` (`username`,`password`,`phone`) values ('%s','%s','%s')"%(phone,'',phone))
            res = db.get_one("select id,username from `users` where phone='%s'"%phone)
            return {'code':200,'meg':'登陆成功','id':res['id'],'username':phone}
    else:
        return {'code':400,'meg':'验证失败'}

@user.route('/userlogin/',methods=['POST','GET'])
def userlogin():
    # username = request.form.get('username')
    # password = request.form.get('password')
    username = request.args.get('username')
    password = request.args.get('password')
    r = redis.Redis()
    bro = r.get('bro_%s'%username)
    tl = (str(r.ttl('bro_%s'%username)/60+1))[0]
    if bro:
        return {'code':403,'meg':'账号被禁5分钟,%s分钟后在登录'%tl}
    db = Db()
    res = db.get_one("select * from `users` where `username`='%s'"%username)
    if res and make_password(password) == res['password']:
        myjwt = MyJwt()
        token = myjwt.encode_jwt_time({'id':res['id'],'username':res['username']},60)
        return {'code':200,'meg':'登录成功','id':res['id'],'username':username,'token':token}
    else:
        ingu = r.get('ingu_%s'%username)
        if ingu:
            try:
               inu = ingu.decode('utf-8')
            except Exception as e:
                pass
            if int(inu)>=3:
                r.set('bro_%s'%username,1)
                r.expire('bro_%s'%username,300)
                t2 = r.ttl('bro_%s'%username)
                return {'code':10010,'meg':'账号被禁5分钟,%s秒后在登录'%t2}
            else:
                r.incr('ingu_%s'%username)
                r.expire('ingu_%s'%username,60)
                return {'code':10011,'meg':'账号或密码错误'}
        else:
            r.set('ingu_%s'%username,1)
            r.expire('ingu_%s'%username,60)
            return {'code':10011,'meg':'账号或密码错误'}

@user.route('/geturls/',methods=['GET'])
def geturls():
    id = request.args.get('id')
    myfile = MyFile()
    myfilelist = myfile.list_dir(id)
    return {'file':myfilelist}

@user.route('/imgFile/',methods=['DELETE'])
def imgFile():
    try:
        id = request.args.get('id')
        filename = request.args.get('filename')
        myfile = MyFile()
        myfile.remove(id,filename)
        myupyun= MyUpyun()
        myupyun.delete(id,filename)
    except Exception as e:
        return {'code':400}
    else:
         return {'code':200}

@user.route('/get_sort_file/',methods=['GET'])
def get_sort_file():
    id = request.args.get('id')
    type = request.args.get('type')
    if type == '1':
        myfile = MyFile()
        myfilelist = myfile.list_dir(id)
        myfilelist.sort(key = lambda m:int(m[:m.find('.')]))
        return {'file':myfilelist}
    else:
        list1 = []
        myfile = MyFile()
        myfilelist = myfile.list_dir(id)
        myfilelist.sort(key = lambda m:m[m.find('.')+1].lower())
        return {'file':myfilelist}


# 登录
@user.route("/login/",methods=['GET'])
async def login():

	# 接收参数
	username = request.args.get("username","")
	password = request.args.get("password")

	phone = request.args.get("phone","")
	code = request.args.get("code")


	if username:

		# 查询逻辑
		sql = " select * from `users` where username = '%s' and password = '%s' " % (username,make_password(password))

		# 实例化对象
		db = Db()

		# 打印sql
		print(sql)

		res = db.get_one(sql)

		# 查询到用户
		if res:

			# 加密操作
			myjwt = MyJwt()

			token = myjwt.encode_jwt({'id':res['id'],"username":res['username']})

			return {'code':200,'id':res['id'],'username':res['username'],"token":token}
		else:
			return {'code':403,'msg':"您的用户名或者密码错误"}
	else:

		# 获取验证码
		r = redis.Redis()
		code_redis = r.get(phone)

		# 转码
		try:
			code_redis = code_redis.decode("utf-8")
		except Exception as e:
			pass

		# 判断第三种情况，过期
		if code_redis is None:

			return {'code':403,'msg':"您的验证码已经过期"}

		# 比对验证码
		if code == code_redis:

			# 查询 该用户是否注册过
			# 实例化对象
			db = Db()

			res = db.get_one(" select id,username from `users` where phone = '%s' " % phone)

			if res:

				return {'code':200,'msg':"登录成功","id":res['id'],"username":res['username']}

			else:

				# 自动注册
				db.insert(" insert into `users` (`username`,`password`,`phone`) values ('%s','%s','%s') " % (phone,'',phone))

				# 查询
				res = db.get_one(" select id,username from `users` where phone = '%s' " % phone)

				return {'code':200,'msg':"登录成功","id":res['id'],"username":res['username']}

		else:

			return {'code':403,'msg':"您的验证码有误"}